#include "viewer.h"
#include "manipulator.h"
#include "gizmos.h"
//#include "gizmomanipulator.h"

#include <osgViewer/api/win32/GraphicsWindowWin32>
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/TrackballManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/StateSetManipulator>
#include <iostream>

//----------------------------------------------------------------------
Viewer::Viewer( long hwnd )
//----------------------------------------------------------------------
{
  _viewer = new osgViewer::Viewer();
  _camera = new osg::Camera();
  _manip  = new Manipulator;

  if( hwnd )
  {
    osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;

    osg::ref_ptr<osg::Referenced> windata = new osgViewer::GraphicsWindowWin32::WindowData((HWND)hwnd);

    traits->x = 0;
    traits->y = 0;
    traits->width = 800;
    traits->height = 600;
    traits->windowDecoration = false;
    traits->doubleBuffer = true;
    traits->sharedContext = 0;
    traits->inheritedWindowData = windata;

    osg::GraphicsContext* gc = osg::GraphicsContext::createGraphicsContext(traits.get());

    _camera->setGraphicsContext(gc);
  }
  _camera->setViewport(new osg::Viewport(0, 0, 800, 600));
  _viewer->addSlave(_camera.get());

  SetRoot( new Node() );
  osg::ref_ptr<osgViewer::WindowSizeHandler> sizeHandler = new osgViewer::WindowSizeHandler;
  _viewer->setCameraManipulator( _manip->Get() );
  _viewer->addEventHandler(new PickModeHandler());
  _viewer->addEventHandler(sizeHandler.get());
  _viewer->addEventHandler( new osgGA::StateSetManipulator(_viewer->getCamera()->getOrCreateStateSet()) );
  _viewer->addEventHandler( new osgViewer::StatsHandler);

  _viewer->realize();

  //toggle fullscreen off
  if(!hwnd)
  {
    osgViewer::Viewer::Windows windows;
    _viewer->getWindows(windows);
    if(windows.size())
    {
      osgViewer::GraphicsWindow* window = windows[0];
      window->setWindowDecoration(true);
      window->setWindowRectangle(100, 100, 800, 600);
      window->grabFocusIfPointerInWindow();
    }
  }

  _t0 = osg::Timer::instance()->tick();
}
//----------------------------------------------------------------------
Viewer::~Viewer(void)
//----------------------------------------------------------------------
{
  delete _manip;
}
//----------------------------------------------------------------------
void Viewer::SetRoot(Node *root)
//----------------------------------------------------------------------
{
  _root = root;
  _viewer->setSceneData(_root->Get());
  _manip->Get()->setNode(_root->Get());
  _manip->Get()->home(0);
}
//----------------------------------------------------------------------
Node* Viewer::GetRoot()
//----------------------------------------------------------------------
{
  return _root;
}
//----------------------------------------------------------------------
void Viewer::SetFov(double fov)
//----------------------------------------------------------------------
{
  double fovy =0;
  double aspectRatio =0;
  double zNear =0;
  double zFar =0;
  _viewer->getCamera()->getProjectionMatrixAsPerspective(fovy, aspectRatio, zNear,zFar );
  _viewer->getCamera()->setProjectionMatrixAsPerspective(fov, aspectRatio, zNear, zFar );
}
//----------------------------------------------------------------------
double Viewer::GetFov()
//----------------------------------------------------------------------
{
  double fovy =0;
  double aspectRatio =0;
  double zNear =0;
  double zFar =0;
  _viewer->getCamera()->getProjectionMatrixAsPerspective(fovy, aspectRatio, zNear, zFar );
  return fovy;
}
